﻿using System.Xml.Serialization;
using System.IO;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using EventPlanner.Models;
using System.Xml.Linq;

using System.Xml;
using EventPlanner.Authorization;

namespace EventPlanner.Controllers
{ 
    public class ContactoController : Controller
    {
        private readonly IEventPlannerContext _db;
        public ContactoController (IEventPlannerContext db) { _db = db; }
               
        public ActionResult ExportData()
        {

            /* Funciona, solo que en el xml el id aparece igual. En la importacion habria que descartar el id
                <ArrayOfContacto xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
             *      <Contacto> <id>0</id> <Nombre>Nombre1</Nombre> <Correo>Email1</Correo> </Contacto>
             *      <Contacto> <id>0</id> <Nombre>Nombre2</Nombre> <Correo>Email2</Correo> </Contacto>
             *  </ArrayOfContacto>
             * 
             * */
            var usuarioActual = _db.GetUsuarioActual();
            var result = from a in _db.Contactoes
                         where a.Creador == usuarioActual

                         select new { a.Nombre, a.Correo, a.id };
            
            
            List<Contacto> list = result.AsEnumerable()
                           .Select(o => new Contacto
                           {
                               id = o.id,
                               Nombre = o.Nombre,
                               Correo = o.Correo
                           }).ToList();

            var stream = new MemoryStream();
            var serialicer = new XmlSerializer(typeof(List<Contacto>));
   

            //Lo transformo en un XML y lo guardo en memoria
            serialicer.Serialize(stream, list);
            stream.Position = 0;


            //devuelvo el XML de la memoria como un archivo
            return File(stream, "text/xml", "contactos_"+usuarioActual+".xml");
            
        }

        //POST
        [HttpPost]
        public ActionResult UploadFile(HttpPostedFileBase file)
        {

            if (file != null && file.ContentLength > 0 && file.ContentType == "text/xml")
            {

                string path = System.IO.Path.Combine(Server.MapPath("~/App_Data"), System.IO.Path.GetFileName(file.FileName));
                file.SaveAs(path);
              
                ImportData(file);

                return RedirectToAction("Index");
            }
            else
                return RedirectToAction("CustomError", "Error", new { MensajeError = "El archivo no es un xml valido o su contenido es vacio." });
        }


        private Boolean existCorreoInDb(Contacto contacto)
        {
            var contact = (from m in _db.Contactoes
                           where (m.Correo == contacto.Correo && m.Creador==contacto.Creador)
                           select m).FirstOrDefault();

            if (contact == null) return false;
            return true;
        }




        public void ImportData(HttpPostedFileBase file)
        {
            Boolean modificado = false;
            XDocument customers = XDocument.Load(Server.MapPath("~/App_Data/"+file.FileName));
            var usuarioActual = _db.GetUsuarioActual();
             var query = from c in customers.Descendants( "Contacto" )
                     
                     select new Contacto
                     {   Creador = usuarioActual,
                         Nombre = c.Element("Nombre").Value,
                         Correo = c.Element("Correo").Value
                     };
          
             foreach (var contact in query)
             {
                 Console.Write(contact.ToString());
                 if (!existCorreoInDb(contact))
                 {
                     contact.Creador = usuarioActual;
                     _db.Contactoes.Add(contact);
                     modificado = true;
                 }

             }

             if (modificado) //guarda los cambios si se añadio al menos un registro
             {
                 _db.SaveChanges();
                
             }
        }



        //
        // GET: /Contacto/
        [Authorize(Roles = "Publisher")]
        public ViewResult Index()
        {
            var usuarioActual = _db.GetUsuarioActual();
            var contactos = from c in _db.Contactoes where c.Creador == usuarioActual select c;
            return View(contactos.ToList());
        }

        //
        // GET: /Contacto/Details/5
        [AutorizarCreadorContacto]
        public ActionResult Details(int id)
        {
            Contacto contacto = _db.GetContacto(id);
            if (contacto.IsValid())
                return View(contacto);
            else
                return RedirectToAction("CustomError", "Error", new { MensajeError = "No existe el contacto" });
        }

        //
        // GET: /Contacto/Create
        [Authorize(Roles = "Publisher")]
        public ActionResult Create()
        {
            return View();
        } 

        //
        // POST: /Contacto/Create
        [Authorize(Roles = "Publisher")]
        [HttpPost]
        public ActionResult Create(Contacto contacto)
        {
            var usuarioActual = _db.GetUsuarioActual();
            if (ModelState.IsValid)
            {
                if (_db.Contactoes.Any(o => o.Correo == contacto.Correo && o.Creador == usuarioActual))
                    return RedirectToAction("CustomError", "Error", new { MensajeError = "El Correo electrónico ya está registrado." });
                else
                {
                    contacto.Creador = usuarioActual;
                    _db.Contactoes.Add(contacto);
                    _db.SaveChanges();
                    return RedirectToAction("Index");
                }                
            }
            return View(contacto);
        }
        
        //
        // GET: /Contacto/Edit/5
        [Authorize(Roles = "Publisher")]
        [AutorizarCreadorContacto]
        public ActionResult Edit(int id)
        {
            Contacto contacto = _db.GetContacto(id);
            if (contacto.IsValid())
                return View(contacto);
            else
                return RedirectToAction("CustomError", "Error", new { MensajeError = "No existe el contacto" });
        }

        //
        // POST: /Contacto/Edit/5
        [HttpPost]
        [Authorize(Roles = "Publisher")]
        public ActionResult Edit(Contacto contacto)
        {
            var usuarioActual = _db.GetUsuarioActual();  
            if (ModelState.IsValid)
            {
                var contact = (from m in _db.Contactoes
                           where m.Correo == contacto.Correo &&
                           m.id !=contacto.id &&
                           m.Creador == usuarioActual
                           select m).FirstOrDefault();

                if (contact == null) //no existe un registro anterior con el nuevo nombre
                {
                   
                    _db.SetModified(contacto);
                    contacto.Creador = usuarioActual;
                    _db.SaveChanges();
                    return RedirectToAction("Index");
                }
                else //ya existe el registro
                {
                    return RedirectToAction("CustomError", "Error", new { MensajeError = "El Correo electrónico ya está registrado." });
                }
            }
            return View(contacto);
        }

        //
        // GET: /Contacto/Delete/5

        [Authorize(Roles = "Publisher")]
        [AutorizarCreadorContacto]
        public ActionResult Delete(int id)
        {
            Contacto contacto = _db.GetContacto(id);
            if(contacto.IsValid())
                return View(contacto);
            else
                return RedirectToAction("CustomError", "Error", new { MensajeError = "No existe el contacto" });
        }

        //
        // POST: /Contacto/Delete/5

        [HttpPost, ActionName("Delete")]
        [Authorize(Roles = "Publisher")]
        public ActionResult DeleteConfirmed(int id)
        {            
            Contacto contacto = _db.Contactoes.Find(id);
            _db.Contactoes.Remove(contacto);
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        [Authorize(Roles = "Publisher")]
        public ActionResult Invitar(int id)
        {
            var usuarioActual = _db.GetUsuarioActual();
            Contacto ct = _db.GetContacto(id);
            if (!ct.IsValid())
                return RedirectToAction("CustomError", "Error", new { MensajeError = "No existe el contacto" });
            Invitacion inv = new Invitacion();
            inv.id = ct.id;
            inv.Nombre = ct.Nombre;
            var evts = from e in _db.Evento 
                       where e.Creador == usuarioActual
                       select new { EventoId = e.id, EventoNombre = e.Nombre };
            if(evts.Count() == 0)
                return RedirectToAction("CustomError", "Error", new { MensajeError = "No hay eventos a los que invitar el contacto" });
            ViewBag.eventos = new SelectList(evts, "EventoId", "EventoNombre");
            return View(inv);
        }

        [Authorize(Roles = "Publisher")]
        [HttpPost]
        public ActionResult Invitar(Invitacion model, int id)
        {
            Contacto contacto = _db.GetContacto(id);
            Evento evento = _db.Evento.Find(model.EventoId);
            if (evento.CupoCompleto())
                return View(contacto);


            //obtengo la lista de participantes al evento y veo si existe alguno con el mismo correo
            List<Participante> a= evento.Participantes.ToList();
            if (a.Any(item => item.Correo == contacto.Correo))
            {
                return RedirectToAction("CustomError", "Error", new { MensajeError = "Un contacto con ese mismo correo ya se encuentra invitado al evento" });
            }
                        
            Participante participante = new Participante();
            participante.Correo = contacto.Correo;
            participante.EventoId = model.EventoId;
            participante.Nombre = contacto.Nombre;
            participante.Confirmado = false;
   
            _db.Participantes.Add(participante);
            _db.SetModified(evento);
            
            evento.Participantes.Add(participante); 
            _db.SaveChanges();
            return RedirectToAction("Index");
        }

        protected override void Dispose(bool disposing)
        {
            ((EventPlannerContext)_db).Dispose();
            base.Dispose(disposing);
        }
    }
}